package com.xhy.documents_collection.service.oss.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xhy.documents_collection.entity.PO.task.DownloadRecord;
import com.xhy.documents_collection.enums.ServiceType;
import com.xhy.documents_collection.exception.BaseException;
import com.xhy.documents_collection.holder.UserHolder;
import com.xhy.documents_collection.cache.UserCache;
import com.xhy.documents_collection.entity.DO.FileDO;
import com.xhy.documents_collection.entity.DO.UploadDO;
import com.xhy.documents_collection.entity.PO.log.SysLog;
import com.xhy.documents_collection.entity.PO.Setting;
import com.xhy.documents_collection.entity.PO.User;
import com.xhy.documents_collection.entity.PO.task.Task;
import com.xhy.documents_collection.entity.PO.task.TaskRecord;
import com.xhy.documents_collection.entity.PO.team.Team;
import com.xhy.documents_collection.service.*;
import com.xhy.documents_collection.service.async.AsyncService;
import com.xhy.documents_collection.service.oss.OssService;
import com.xhy.documents_collection.service.sys.SysSettingService;
import com.xhy.documents_collection.service.task.DownloadRecordService;
import com.xhy.documents_collection.service.task.TaskRecordService;
import com.xhy.documents_collection.service.task.TaskService;
import com.xhy.documents_collection.service.task.TroopUserService;
import com.xhy.documents_collection.service.team.TeamService;
import com.xhy.documents_collection.utils.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Author: Xhy
 * CreateTime: 2022-11-19 21:21
 */
@Service
public class OssServiceImpl implements OssService {


    @Resource
    private TeamService teamService;

    @Resource
    private TaskService taskService;

    @Resource
    private TaskRecordService taskRecordService;

    @Resource
    private DownloadRecordService downloadRecordService;

    @Resource
    private AsyncService asyncService;

    @Override
    public R captionUpload(MultipartFile file, String taskRecordId) {

        // 拼接文件路径,团队名称+任务名称+文件名称
        // 获取任务id
        TaskRecord taskRecord = taskRecordService.get(taskRecordId);

        // 是否存在该记录
        if (ObjectUtils.isEmpty(taskRecord)){
            return R.error().message("记录不存在");
        }
        long fileSize = file.getSize();
        if (fileSize == 0L){
            return R.error().message("上传文件大小不可为0KB");
        }
        // 是否已达到容量
        Integer teamId = taskService.getOne(new QueryWrapper<Task>().eq("id", taskRecord.getTId()).select("t_id")).getTId();
        Team team = teamService.getById(teamId);
        if (team.getFileSizeUsed() >= team.getFileSizeCapacity()){
            return R.error().message("团队文件容量已用完");
        }
        // 校验文件上传大小
        Setting setting = sysSettingService.getById(1);
        Long limitFileSize = Long.valueOf(setting.getRequestFileSize() * 1024 * 1024);
        if (fileSize >limitFileSize){
            return R.error().message("文件大小限制,不能超过:"+setting.getRequestFileSize()+"MB");
        }

        Integer userId = UserHolder.get();
        UploadDO uploadDO = new UploadDO();
        FileDO fileDO = new FileDO();
        try {
            fileDO.setInputStream(file.getInputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 获取任务
        Task task = taskService.getById(taskRecord.getTId());
        String fileName = file.getOriginalFilename().replace("+", "");
        if (!ObjectUtils.isEmpty(task.getFileNameTemplate())){
            User user = userService.getById(taskRecord.getUId());
            try {
                String pos = fileName.substring(fileName.lastIndexOf("."));
                fileName = Template.parseTemp(task.getFileNameTemplate(),user);
                fileName+=pos;
            } catch (Exception e) {
                return R.error().message("解析模板出错,请寻找团队负责人查看模板");
            }
        }
        fileDO.setFileName(fileName);
        fileDO.setFileSize(fileSize);
        uploadDO.setFileDO(fileDO);
        uploadDO.setTeam(team);
        uploadDO.setTaskRecord(taskRecord);
        asyncService.upload(uploadDO);
        return R.ok().message("上传成功,请稍后查看上传状态");
    }

    @Resource
    private TroopUserService troopUserService;

    // 填充taskRecord信息以及上传



    @Override
    @Transactional
    public R captionSendBack(String taskRecordId) {
        if (ObjectUtils.isEmpty(taskRecordId)){
            return R.error().message("请选择退回的文件");
        }

        TaskRecord taskRecord = taskRecordService.get(taskRecordId);
        if (!taskRecord.getIsSubmit()){
            return R.error().message("没有要退回的文件");
        }

        Integer uId = UserHolder.get();
        asyncService.deleteFile(taskRecord,uId);
        return R.ok().message("退回成功");
    }

    @Override
    public R download(String taskRecordIds, HttpServletResponse response) {
        if (ObjectUtils.isEmpty(taskRecordIds)){
            return R.error().message("请选择下载的文件");
        }
        List<String> recordIds = Arrays.asList(taskRecordIds.split(","));
        Integer uId = UserHolder.get();
        // 查出filePath不为空的记录
        List<TaskRecord> records = taskRecordService.list(new QueryWrapper<TaskRecord>().in("id", recordIds))
                .stream()
                .filter(record -> !ObjectUtils.isEmpty(record.getFilePath()))
                .distinct()
                .collect(Collectors.toList());
        asyncService.downloadFiles(records,uId);

        return R.ok().message("正在下载中,下载后的文件请在下载记录中查看");
    }

    @Resource
    private SysSettingService sysSettingService;


    /**
     * 判断当前时间是否可以提交任务
     * @param task
     * @return
     */
    private R verifyTime(Task task){
        // 任务是否在规定时间内
        // 当前时间大于最晚提交时间
        if (new Date().compareTo(task.getEndTime()) == 1){
            return R.error().message("任务已结束");
        }
        // 不允许提前交
        if (new Date().compareTo(task.getStartTime()) == -1){

            return R.error().message("任务还没开始");
        }

        // 不允许截止后提交
        return R.ok();
    }

    @Resource
    private UserService userService;

    @Override
    public R userUpload(MultipartFile file, String taskRecordId) {

        Integer uId = UserHolder.get();
        TaskRecord taskRecord = taskRecordService.getOne(new QueryWrapper<TaskRecord>().eq("id", taskRecordId).eq("u_id", uId));
        if (ObjectUtils.isEmpty(taskRecord)){
            return R.error().message("记录不存在");
        }
        Task task = taskService.getOne(new QueryWrapper<Task>().eq("id", taskRecord.getTId()).select("t_id","end_time","start_time","file_name_template"));
        R r = verifyTime(task);
        if (!r.getState()){
            return r;
        }
        long fileSize = file.getSize();
        if (fileSize == 0L){
            return R.error().message("上传文件大小不可为0KB");
        }
        // 校验文件上传大小
        Setting setting = sysSettingService.getById(1);
        Long limitFileSize = Long.valueOf(setting.getRequestFileSize() * 1024 * 1024);
        if (fileSize >limitFileSize){
            return R.error().message("文件大小限制,不能超过:"+setting.getRequestFileSize()+"MB");
        }
        // 是否已达到容量
        Integer teamId = task.getTId();
        Team team = teamService.getById(teamId);
        if (team.getFileSizeUsed() >= team.getFileSizeCapacity()){
            return R.error().message("团队文件容量已用完");
        }


        UploadDO uploadDO = new UploadDO();
        FileDO fileDO = new FileDO();
        try {
            fileDO.setInputStream(file.getInputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
        String fileName = file.getOriginalFilename().replace("+", "");
        if (!ObjectUtils.isEmpty(task.getFileNameTemplate())){
            User user = userService.getById(uId);
            try {
                String pos = fileName.substring(fileName.lastIndexOf("."));
                fileName = Template.parseTemp(task.getFileNameTemplate(),user);
                fileName+=pos;
            } catch (Exception e) {
                return R.error().message("解析模板出错,请寻找团队负责人查看模板");
            }
        }
        fileDO.setFileName(fileName);
        fileDO.setFileSize(fileSize);
        uploadDO.setFileDO(fileDO);
        uploadDO.setTaskRecord(taskRecord);
        uploadDO.setTeam(team);
        uploadDO.setUId(uId);
        asyncService.upload(uploadDO);
        return r.message("上传成功,请稍后查看上传状态");
    }




    @Override
    public R userSendBack(String taskRecordId) {

        Integer uId = UserHolder.get();
        TaskRecord taskRecord = taskRecordService.getOne(new QueryWrapper<TaskRecord>().eq("id", taskRecordId).eq("u_id", uId));
        if (!taskRecord.getIsSubmit()){
            return R.ok().message("没有要撤回的文件");
        }

        // 当前时间大于最晚提交时间
        Task task = taskService.getOne(new QueryWrapper<Task>().eq("id", taskRecord.getTId()).select("t_id","end_time","start_time"));
        R r = verifyTime(task);
        if (!r.getState()){
            return r;
        }
        asyncService.deleteFile(taskRecord,uId);

        return r.message("撤回成功,请稍后查看撤回状态");
    }

    @Override
    public void downloadFile(Integer id, HttpServletResponse response) {

        Integer userId = UserHolder.get();

        // 成员
        TaskRecord taskRecord = taskRecordService.getOne(new LambdaQueryWrapper<TaskRecord>().eq(TaskRecord::getId, id).eq(TaskRecord::getUId, userId));

        // 负责人
        DownloadRecord downloadRecord = downloadRecordService.getOne(new LambdaQueryWrapper<DownloadRecord>().eq(DownloadRecord::getId, id).eq(DownloadRecord::getUserId, userId));

        if (ObjectUtils.isEmpty(taskRecord) &&ObjectUtils.isEmpty(downloadRecord)){
            throw new BaseException(500,"记录不存在");
        }

        if (!ObjectUtils.isEmpty(taskRecord)){
            OSSUtil.downloadFile(taskRecord.getFilePath(),response);
        }else {
            OSSUtil.downloadFile(downloadRecord.getFilePath(),response);
        }
    }
}



